package com.letoken.platform.job.jobhandler.monitor;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.letoken.platform.pub.annotation.auth.NotAuthorization;
import com.letoken.platform.pub.enums.LetokenApiResponseEnum;
import com.letoken.platform.pub.enums.LetokenTokenTypeEnum;
import com.letoken.platform.pub.enums.TokenTransactionStatusEnum;
import com.letoken.platform.pub.enums.TokenTransactionTypeEnum;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.pub.res.ApiResponse;
import com.letoken.platform.repo.admin.dao.AdminFundConfigMapper;
import com.letoken.platform.repo.admin.po.AdminFundConfig;
import com.letoken.platform.repo.app.dao.*;
import com.letoken.platform.repo.app.manager.TokenManager;
import com.letoken.platform.repo.app.po.*;
import com.letoken.platform.repo.app.req.user.FundTransferReq;
import com.letoken.platform.repo.app.req.user.UserLevelReq;
import com.letoken.platform.repo.mall.dao.*;
import com.letoken.platform.repo.mall.po.*;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Log4j2
public class LetToCapaJob {

    @Resource
    private AppUserIssueMapper appUserIssueMapper;

    @Resource
    private AppUserIssueRecordMapper appUserIssueRecordMapper;


    @Resource
    private AppMallIssueMapper appMallIssueMapper;

    @Resource
    private AppMallIssueRecordMapper appMallIssueRecordMapper;

    @Resource
    private AppMallAmbSummaryMapper appMallAmbSummaryMapper;

    @Resource
    private AppMallAmbassadorRecordMapper appMallAmbassadorRecordMapper;

    @Resource
    private AppFundInfoMapper appFundInfoMapper;

    @Resource
    private AppBalanceWalletMapper appBalanceWalletMapper;

    @Resource
    private AppUserWalletMapper appUserWalletMapper;

    @Resource
    private TokenManager tokenManager;

    @Resource
    private AppMallAccountMapper appMallAccountMapper;


    @XxlJob("initLET")
    public ApiResponse initLET() {
        // try{
        //铸币发行待流通兑换
        /*List<AppUserIssue> issueUserIdList = appUserIssueMapper.getIssueUserIdList();
        for (AppUserIssue appUserIssue:issueUserIdList) {
            AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appUserIssue.getUserId()));
            if (ObjectUtils.isEmpty(w))continue;
            List<AppUserIssueRecord> appUserIssueRecords =  appUserIssueRecordMapper.getWaitCirculation(appUserIssue.getUserId());
            for (AppUserIssueRecord appUserIssueRecord:appUserIssueRecords) {
                appUserIssueRecord.setWaitCirculation(BigDecimal.ZERO);
                appUserIssueRecord.setStatus(1);
                appUserIssueRecord.updateById();
            }
            BigDecimal amount = appUserIssue.getCirculationRemain().divide(new BigDecimal(2));
            appUserIssue.setCirculationRemain(BigDecimal.ZERO);
            appUserIssue.updateById();


            AppUserWallet updateW = new AppUserWallet();
            updateW.setId(w.getId());
            updateW.setAvailableBalance(w.getAvailableBalance().add(amount));
            appUserWalletMapper.updateById(updateW);

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(appUserIssue.getUserId());
            assetHistory.setType(TokenTransactionTypeEnum.ISSUE_EXCHANGE.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
            assetHistory.setAmount(amount);
            assetHistory.setBalance(updateW.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.setUpdateTime(assetHistory.getCreateTime());
            assetHistory.insert();

        }

        //消费发行待流通兑换
        List<AppMallIssue>  mallIssueUserIdList = appMallIssueMapper.getIssueUserIdList();
        for (AppMallIssue appMallIssue:mallIssueUserIdList) {
            AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appMallIssue.getUserId()));
            if (ObjectUtils.isEmpty(w))continue;
            List<AppMallIssueRecord> appUserIssueRecords =  appMallIssueRecordMapper.getWaitCirculation(appMallIssue.getUserId());
            for (AppMallIssueRecord appMallIssueRecord:appUserIssueRecords) {
                appMallIssueRecord.setWaitCirculation(BigDecimal.ZERO);
                appMallIssueRecord.setStatus(1);
                appMallIssueRecord.updateById();
            }
            BigDecimal amount = appMallIssue.getCirculationRemain().divide(new BigDecimal(5));
            appMallIssue.setCirculationRemain(BigDecimal.ZERO);
            appMallIssue.updateById();

            // AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appMallIssue.getUserId()));
            AppUserWallet updateW = new AppUserWallet();
            updateW.setId(w.getId());
            updateW.setAvailableBalance(w.getAvailableBalance().add(amount));
            appUserWalletMapper.updateById(updateW);

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(appMallIssue.getUserId());
            assetHistory.setType(TokenTransactionTypeEnum.MALL_ISSUE_EXCHANGE.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
            assetHistory.setAmount(amount);
            assetHistory.setBalance(updateW.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.setUpdateTime(assetHistory.getCreateTime());
            assetHistory.insert();
        }*/

        //全球分红待流通兑换
        /*List<AppMallAmbSummary>  mallAmbSummaryList = appMallAmbSummaryMapper.getIssueUserIdList();
        for (AppMallAmbSummary appMallAmbSummary:mallAmbSummaryList) {
            AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appMallAmbSummary.getUserId()));
            if (ObjectUtils.isEmpty(w))continue;
           *//* List<AppMallAmbassadorRecord> appMallAmbassadorRecords =  appMallAmbassadorRecordMapper.getWaitCirculation(appMallAmbSummary.getUserId());
            for (AppMallAmbassadorRecord appMallAmbassadorRecord:appMallAmbassadorRecords) {
                appMallAmbassadorRecord.setWaitCirculation(BigDecimal.ZERO);
                appMallAmbassadorRecord.setStatus(1);
                appMallAmbassadorRecordMapper.updateById(appMallAmbassadorRecord);
            }*//*
            BigDecimal amount = appMallAmbSummary.getCirculationRemain().divide(new BigDecimal(5));
            appMallAmbSummary.setCirculationRemain(BigDecimal.ZERO);
            appMallAmbSummaryMapper.updateById(appMallAmbSummary);


            // AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appMallAmbSummary.getUserId()));
            AppUserWallet updateW = new AppUserWallet();
            updateW.setId(w.getId());
            updateW.setAvailableBalance(w.getAvailableBalance().add(amount));
            appUserWalletMapper.updateById(updateW);

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(appMallAmbSummary.getUserId());
            assetHistory.setType(TokenTransactionTypeEnum.AMB_ISSUE_EXCHANGE.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
            assetHistory.setAmount(amount);
            assetHistory.setBalance(updateW.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.setUpdateTime(assetHistory.getCreateTime());
            assetHistory.insert();
        }*/
       // appMallAmbassadorRecordMapper.updateAmbassadorRecord();

        //基金赎回
        List<AppFundInfo> appFundInfos = appFundInfoMapper.getSumFundByUserId();
        for (AppFundInfo appFundInfo:appFundInfos) {
            AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appFundInfo.getUserId()));
            if (ObjectUtils.isEmpty(w))continue;
            appFundInfoMapper.updateTypeByUserId(appFundInfo.getUserId());
            // AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appFundInfo.getUserId()));
            AppUserWallet updateW = new AppUserWallet();
            updateW.setId(w.getId());
            updateW.setAvailableBalance(w.getAvailableBalance().add(appFundInfo.getFund()));
            appUserWalletMapper.updateById(updateW);

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(appFundInfo.getUserId());
            assetHistory.setType(TokenTransactionTypeEnum.FUND_EXCHANGE.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
            assetHistory.setAmount(appFundInfo.getFund());
            assetHistory.setBalance(updateW.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.setUpdateTime(assetHistory.getCreateTime());
            assetHistory.insert();
        }

       /* List<AppBalanceWallet> balanceWallets = appBalanceWalletMapper.allBalanceUser();
        for (AppBalanceWallet appBalanceWallet:balanceWallets) {
            AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appBalanceWallet.getUserId()));
            if (ObjectUtils.isEmpty(w))continue;
            AppBalanceWallet appBalanceWallet1 = appBalanceWalletMapper.selectForUpdate(appBalanceWallet.getId());
            AppBalanceWallet appBalanceWallet2 = new AppBalanceWallet();
            appBalanceWallet2.setId(appBalanceWallet1.getId());
            appBalanceWallet2.setBalance(BigDecimal.ZERO);
            appBalanceWalletMapper.updateById(appBalanceWallet2);

            //AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(appBalanceWallet.getUserId()));
            AppUserWallet updateW = new AppUserWallet();
            updateW.setId(w.getId());
            updateW.setAvailableBalance(w.getAvailableBalance().add(appBalanceWallet1.getBalance()));
            appUserWalletMapper.updateById(updateW);

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(appBalanceWallet.getUserId());
            assetHistory.setType(TokenTransactionTypeEnum.BALANCE_EXCHANGE.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
            assetHistory.setAmount(appBalanceWallet1.getBalance());
            assetHistory.setBalance(updateW.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.setUpdateTime(assetHistory.getCreateTime());
            assetHistory.insert();
        }*//*}catch (Exception e){
            log.info(e.getMessage());
        }*/
        return ApiResponse.create("ok");
    }


    @XxlJob("initCAPA")
    public ApiResponse initCAPA() {
        try{
            List<AppUserWallet> walletList = appUserWalletMapper.getWalletList();
            Token token = tokenManager.queryTokenByCurrency("CAP");
            BigDecimal price = new BigDecimal(token.getUsdPrice());
            for (AppUserWallet appUserWallet:walletList) {
                BigDecimal amount;
                amount = appUserWallet.getAvailableBalance();
                BigDecimal money = appUserWallet.getAvailableBalance();
                appUserWallet.setAvailableBalance(BigDecimal.ZERO);
                if(appUserWallet.getTokenId().equals(4)){
                    amount =  price.multiply(amount);
                }
                appUserWallet.updateById();

                AppUserWallet w = appUserWalletMapper.selectForUpdate(checkoutCAPA(appUserWallet.getUserId()));
                AppUserWallet updateW = new AppUserWallet();
                updateW.setId(w.getId());
                updateW.setAvailableBalance(w.getAvailableBalance().add(amount));
                appUserWalletMapper.updateById(updateW);

                AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
                assetHistory.setUserId(appUserWallet.getUserId());
                assetHistory.setType(TokenTransactionTypeEnum.OHTER_TO_CAPA.getValue());
                assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
                assetHistory.setTokenId(LetokenTokenTypeEnum.CAPA.getId());
                assetHistory.setAmount(amount);
                assetHistory.setBalance(updateW.getAvailableBalance());
                assetHistory.setCreateTime(LocalDateTime.now());
                assetHistory.setUpdateTime(assetHistory.getCreateTime());
                assetHistory.insert();


                AppUserAssetsHistory assetHistory1 = new AppUserAssetsHistory();
                assetHistory1.setUserId(appUserWallet.getUserId());
                assetHistory1.setType(TokenTransactionTypeEnum.OHTER_TO_CAPA.getValue());
                assetHistory1.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
                assetHistory1.setTokenId(appUserWallet.getTokenId());
                assetHistory1.setAmount(money.negate());
                assetHistory1.setBalance(appUserWallet.getAvailableBalance());
                assetHistory1.setCreateTime(LocalDateTime.now());
                assetHistory1.setUpdateTime(assetHistory.getCreateTime());
                assetHistory1.insert();
            }
        }catch (Exception e){
            log.info("");
        }
        return ApiResponse.create("ok");
    }



    private Integer checkout(Integer userId){
        //Integer balanceId = appBalanceWalletMapper.getIdByUserId(LetokenTokenTypeEnum.LET.getId(),req.getUserId());
        Integer walletId = appUserWalletMapper.checkoutTokenIdAndUserId(LetokenTokenTypeEnum.LET.getId(), userId);
        if (/*ObjectUtils.isEmpty(balanceId) ||*/ ObjectUtils.isEmpty(walletId)){
            /*throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_051);*/
            return 10000000;
        }
        return walletId;
    }

    private Integer checkoutCAPA(Integer userId){
        //Integer balanceId = appBalanceWalletMapper.getIdByUserId(LetokenTokenTypeEnum.LET.getId(),req.getUserId());
        Integer walletId = appUserWalletMapper.checkoutTokenIdAndUserId(LetokenTokenTypeEnum.CAPA.getId(), userId);
        if (/*ObjectUtils.isEmpty(balanceId) ||*/ ObjectUtils.isEmpty(walletId)){
            // throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_051);
            return 10000000;
        }
        return walletId;
    }

    @XxlJob("updateDate")
    @Transactional
    public ApiResponse updateDate(){
       List<AppFundInfo> infoList = appFundInfoMapper.updateDateList();
        for (AppFundInfo appFundInfo:infoList) {
            peerLevelReward(appFundInfo.getUserId(),appFundInfo.getFund());
        }
        return ApiResponse.create("ok");
    }

    private void peerLevelReward(Integer userId,BigDecimal amount){
        BigDecimal rate = appFundInfoMapper.getMaxLevelRate();
        List<UserLevelReq> user = appFundInfoMapper.selectUserLevelPeerRate(userId);
        //上一次拿奖励的人等级
        Integer level = 0;
        BigDecimal levelRate = BigDecimal.ZERO;
        if(user.size()>0){
            for (UserLevelReq req:user) {
                if(req.getLevel() > level && rate.compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal rates= req.getRate();
                    req.setRate(req.getRate().subtract(levelRate));
                    BigDecimal ss = rate.compareTo(req.getRate())>0?req.getRate():rate;
                    BigDecimal reward = amount.multiply(ss);
                    rate = rate.compareTo(req.getRate())>0?rate.subtract(req.getRate()):BigDecimal.ZERO;
                    level=req.getLevel();
                    levelRate = rates;
                    /*BigDecimal bigDecimal = appFundInfoMapper.sumAmount(req.getUserId(),5);
                    if(bigDecimal.compareTo(BigDecimal.ZERO)<= 0){
                       continue;
                    }*/
                    Integer walletId = appUserWalletMapper.checkoutTokenIdAndUserId(LetokenTokenTypeEnum.LET.getId(), req.getUserId());
                    AppUserWallet w = appUserWalletMapper.selectForUpdate(walletId);
                    AppUserWallet updateW = new AppUserWallet();
                    updateW.setId(w.getId());
                    updateW.setAvailableBalance(w.getAvailableBalance().add(reward));
                    appUserWalletMapper.updateById(updateW);

                    AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
                    assetHistory.setUserId(req.getUserId());
                    assetHistory.setType(TokenTransactionTypeEnum.FUND_LEVEL_REWARD.getValue());
                    assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
                    assetHistory.setTokenId(LetokenTokenTypeEnum.LET.getId());
                    assetHistory.setAmount(reward);
                    assetHistory.setBalance(updateW.getAvailableBalance());
                    assetHistory.setCreateTime(LocalDateTime.now());
                    assetHistory.setUpdateTime(assetHistory.getCreateTime());
                    assetHistory.insert();
                }
            }
        }

    }


    @Resource
    AdminFundConfigMapper adminFundConfigMapper;


    @XxlJob("income")
    public  void income() {
        List<Integer> fundUserIdList= appFundInfoMapper.getFundUserId();

        List<AdminFundConfig> configList = adminFundConfigMapper.selectList(new QueryWrapper<>());
        for (Integer userId:fundUserIdList) {
            List<AppFundInfo> infoList = appFundInfoMapper.getFundByUserIdUpdate(userId);
            //自己可拿奖励总额
            BigDecimal sumFund = BigDecimal.ZERO;
            //给上级带来奖励的总额
            BigDecimal  award = BigDecimal.ZERO;
            for (AppFundInfo appFundInfo:infoList) {
                BigDecimal rate = configList.stream().filter(s->s.getId().equals(appFundInfo.getFundId())).collect(Collectors.toList()).get(0).getRate();
                appFundInfo.setAmount(appFundInfo.getFund().multiply(rate));
                sumFund = sumFund.add(appFundInfo.getAmount());
                if(appFundInfo.getState().equals(1)){
                    award = award.add(appFundInfo.getAmount());
                }
            }
            if(award.compareTo(BigDecimal.ZERO)>0)bonus(userId,award);
        }

    }


    @Resource
    AdminFundLevelConfigMapper adminFundLevelConfigMapper;

    public void bonus(Integer userId,BigDecimal money) {
        try {
            BonusDto dto = new BonusDto();
            dto.setAmount(money);
            dto.setUserId(userId);
            BigDecimal amount = dto.getAmount();
            BigDecimal rate =  appFundInfoMapper.getMaxfundRate();
            List<UserLevelReq> list = appFundInfoMapper.selectUserLevel(dto.getUserId());
            Integer level = 0;
            BigDecimal levelRate = BigDecimal.ZERO;
            List<AdminFundLevelConfig> configList = adminFundLevelConfigMapper.getList();
            if(list.size()>0){
                for (UserLevelReq req:list) {

                    BigDecimal  bigDecimal = appFundInfoMapper.sumAmount(req.getUserId(),1);
                    if(req.getLevel() > level && rate.compareTo(BigDecimal.ZERO) > 0){
                        BigDecimal rates= req.getRate();
                        req.setRate(req.getRate().subtract(levelRate));
                        BigDecimal ss = rate.compareTo(req.getRate())>0?req.getRate():rate;
                        BigDecimal reward = amount.multiply(ss);
                        rate = rate.compareTo(req.getRate())>0?rate.subtract(req.getRate()):BigDecimal.ZERO;
                        level = req.getLevel();
                        levelRate = rates;
                        BigDecimal sss = configList.stream().filter(s->s.getLevel().equals(req.getLevel())).collect(Collectors.toList()).get(0).getFundAmount();
                        if(bigDecimal.compareTo(sss)<0 || req.getLevel()<6)continue;
                        AppUserAssetsHistory appUserAssetsHistory = new AppUserAssetsHistory();
                        appUserAssetsHistory.setUserId(req.getUserId());
                        appUserAssetsHistory.setType(TokenTransactionTypeEnum.FUND_BONUS.getValue());
                        appUserAssetsHistory.setStatus(1);
                        appUserAssetsHistory.setSn(req.getUserId().toString());
                        appUserAssetsHistory.setTokenId(2);
                        appUserAssetsHistory.setAmount(reward);
                        appUserAssetsHistory.setCreateTime(LocalDateTime.now());
                        appUserAssetsHistory.setUpdateTime(LocalDateTime.now());
                        appUserAssetsHistory.insert();


                        AppUserWallet w = appUserWalletMapper.selectForUpdate(checkout(req.getUserId()));
                        if (ObjectUtils.isEmpty(w))continue;
                        AppUserWallet updateW = new AppUserWallet();
                        updateW.setId(w.getId());
                        updateW.setAvailableBalance(w.getAvailableBalance().add(reward));
                        appUserWalletMapper.updateById(updateW);
                        try {
                            AppUserAssetsHistory updateAssetHistory = new AppUserAssetsHistory();
                            updateAssetHistory.setBalance(updateW.getAvailableBalance());
                            updateAssetHistory.setId(appUserAssetsHistory.getId());
                            updateAssetHistory.updateById();
                        }catch (Exception e){
                            log.error("更新余额失败 id{} eMsg{}", appUserAssetsHistory.getId(), e.getMessage());
                        }


                    }
                }
            }
        } catch (Exception ex) {
            log.error("MQ >> imLogin error！ [{}]", ex.getMessage());
        }
    }

    @Data
    public static class BonusDto implements Serializable {
        private Integer userId;
        private BigDecimal amount;
    }

}
